package com.product.magina.webserviceclient.wsClient;

import com.alibaba.fastjson.JSON;
import com.magina.common.model.UserInfo;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.endpoint.ClientImpl;
import org.apache.cxf.endpoint.Endpoint;
import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory;
import org.apache.cxf.service.model.*;
import org.assertj.core.util.Lists;
import org.junit.Test;

import javax.xml.namespace.QName;
import java.beans.PropertyDescriptor;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 *  CXF 调用webService 复杂参数Demo
 *   @author：anti_magina
 *   @date：2019-03-29 16:49:26
 */
public class WS_CXF_Advanced_Client {
    private static  String   wsdlUrl="http://localhost:8081/services/TestService?wsdl";
    //	private static final QName SERVICE_NAME = new QName("namespace", "serviceName");
    private static final QName SERVICE_NAME = new QName("http://service.webserviceclient.magina.product.com", "TestService");
    /**
     * 网上流传的方法【初始化复杂，后续有改进版】
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
        // 创建动态客户端
        JaxWsDynamicClientFactory factory = JaxWsDynamicClientFactory.newInstance();
        // 创建客户端连接
        Client client = factory.createClient(wsdlUrl, SERVICE_NAME);
        ClientImpl clientImpl = (ClientImpl) client;
        Endpoint endpoint = clientImpl.getEndpoint();
        // Make use of CXF service model to introspect the existing WSDL
        ServiceInfo serviceInfo = endpoint.getService().getServiceInfos().get(0);
        // 创建QName来指定NameSpace和要调用的service
        //第二个参数localPart可以取wsdl里面找.也可以再method+SoapBinding
       QName bindingName = new QName(
                "http://service.webserviceclient.magina.product.com",
                "TestServiceSoapBinding");
        BindingInfo binding = serviceInfo.getBinding(bindingName);
        // 创建QName来指定NameSpace和要调用的方法
        QName opName = new QName(
                "http://service.webserviceclient.magina.product.com", "getUser");
        BindingOperationInfo boi = binding.getOperation(opName);
//        BindingMessageInfo inputMessageInfo = boi.getInput();
        BindingMessageInfo inputMessageInfo = null;
        if (!boi.isUnwrapped()) {
            //OrderProcess uses document literal wrapped style.
            inputMessageInfo = boi.getWrappedOperation().getInput();
        } else {
            inputMessageInfo = boi.getUnwrappedOperation().getInput();
        }
        List<MessagePartInfo> parts = inputMessageInfo.getMessageParts();
        MessagePartInfo partInfo = parts.get(0); // Input class is Order
        // 取得对象实例
        Class<?> partClass = partInfo.getTypeClass();
        Object inputObject = partClass.newInstance();
        PropertyDescriptor custProperty = new PropertyDescriptor("userName", partClass);
        custProperty.getWriteMethod().invoke(inputObject, "C001");
        PropertyDescriptor agePro = new PropertyDescriptor("age", partClass);
        agePro.getWriteMethod().invoke(inputObject, 12);
        Object[] result = client.invoke(opName, inputObject);
        String userJson = JSON.toJSONString(result[0]);
        UserInfo userInfo = JSON.parseObject(userJson,UserInfo.class);
        System.out.println("return messsage: " + userInfo.toString());
        //return messsage: UserInfo{userName='C001', age=12}
    }

    @Test
    public void testCxf01() throws Exception {
        Map<String,Object> params = new HashMap<>();
        params.put("alisename","测试数据怕");
        params.put("aliseid",123123);
        String result = dynamicCallWebServiceByCXF(wsdlUrl,"sendMessageById",
                "http://service.webserviceclient.magina.product.com","TestService",params);
        System.out.println(result);
        //success =hello 测试数据怕your id is: 123123
    }

    @Test
    public void testCxf02() throws Exception {
        Map<String,Object> params = new HashMap<>();
        List<UserInfo> userInfoList = Lists.newArrayList();
        UserInfo userInfo =new UserInfo();
        userInfo.setUserName("张三哦");
        userInfo.setAge(12312);
        UserInfo userInfo1 =new UserInfo();
        userInfo1.setUserName("里斯哦");
        userInfo1.setAge(324343);
        userInfoList.add(userInfo1);
        userInfoList.add(userInfo);
        params.put("userList",userInfoList);
        String userName = "是否能i需改名字呢?";
        params.put("userName",userName);
        String result = dynamicCallWebServiceByCXF(wsdlUrl,"getUserListByName",
                "http://service.webserviceclient.magina.product.com","TestService",params);
        System.out.println(result);
        //success =[{"userName":"是否能i需改名字呢?","age":324343},{"userName":"是否能i需改名字呢?","age":12312}]
    }

    /**
     *
     * @param wsdlUrl  wsdl的地址：http://localhost:8081/services/TestService?wsdl
     * @param methodName 调用的方法名称 sendMessageById
     * @param targetNamespace 命名空间 http://service.webserviceclient.magina.product.com
     * @param name  name TestService
     * @param map 参数集合
     * @throws Exception
     */
    public  static String dynamicCallWebServiceByCXF(String wsdlUrl,String methodName,String targetNamespace,String name,Map<String,Object> map)throws Exception{
        //临时增加缓存，增加创建速度
            // 创建动态客户端
            JaxWsDynamicClientFactory factory = JaxWsDynamicClientFactory.newInstance();
            // 创建客户端连接
            Client client = factory.createClient(wsdlUrl);
            ClientImpl clientImpl = (ClientImpl) client;
            Endpoint endpoint = clientImpl.getEndpoint();
            System.out.println("初始化");

        // Make use of CXF service model to introspect the existing WSDL
        ServiceInfo serviceInfo = endpoint.getService().getServiceInfos().get(0);
        // 创建QName来指定NameSpace和要调用的service
        String localPart=name+"SoapBinding";
        QName bindingName = new QName(targetNamespace, localPart);
        BindingInfo binding = serviceInfo.getBinding(bindingName);

        //创建QName来指定NameSpace和要调用的方法绑定方法
        QName opName = new QName(targetNamespace, methodName);//selectOrderInfo

        BindingOperationInfo boi = binding.getOperation(opName);
//		BindingMessageInfo inputMessageInfo = boi.getInput();
        BindingMessageInfo inputMessageInfo = null;
        if (!boi.isUnwrapped()) {
            //OrderProcess uses document literal wrapped style.
            inputMessageInfo = boi.getWrappedOperation().getInput();
        } else {
            inputMessageInfo = boi.getUnwrappedOperation().getInput();
        }
        List<MessagePartInfo> parts = inputMessageInfo.getMessageParts();

        /***********************以下是初始化参数，组装参数；处理返回结果的过程******************************************/
        Object[] parameters = new Object[parts.size()];
        for(int m=0;m<parts.size();m++){

            MessagePartInfo  part=parts.get(m);
//            System.out.println(part.getName());//{http://service.webserviceclient.magina.product.com}aliseid
//            System.out.println(part.getElementQName());//aliseid
//            System.out.println(part.getConcreteName());//aliseid
            //实例化对象
            Object initDomain=null;
            // 取得对象实例
            Class<?> partClass = part.getTypeClass();//OrderInfo.class;
            System.out.println(partClass.getCanonicalName()); // GetAgentDetails
            String key = part.getElementQName().getLocalPart();
            if(map.containsKey(key)){
                Object mapResult = map.get(key);
                //如果是数组
             if(partClass.getCanonicalName().indexOf("[]")>-1){
                //转换数组
                initDomain=JSON.parseArray(JSON.toJSONString(mapResult),partClass.getComponentType());
            }else{
                initDomain=JSON.parseObject(JSON.toJSONString(mapResult),partClass);
            }
            }
            parameters[m]=initDomain;

        }
        //定义返回结果集
        Object[] result=null;
        //普通参数情况 || 对象参数情况  1个参数 ||ArryList集合
        try {
            result = client.invoke(opName,parameters);
        }catch (Exception ex){
            ex.printStackTrace();
            return "参数异常"+ex.getMessage();
        }
        //返回调用结果
        if(result.length>0){
            return  "success =" +JSON.toJSON(result[0]).toString();
        }
        return  "invoke success, but is void ";
    }


}
